﻿//
//
var gServiceUrl = "http://xml.weather.co.ua/1.2/forecast/";
var gNumberOfDays = 1;
var gForecastVersion = 1.2;
var gPollTimeout = 15 * 60 * 1000;

function WeatherGadget() {
    var self = this;
    var requestTimeout;
    var options = new Options();
    var pollTimeout;

    this.request;
    this.onDataReady;

    options.load();

    function parseResponse() {

        if (!self.request) {
            return;
        }

        with (self.request) {
            if (readyState == 4) {

                clearTimeout(requestTimeout);

                switch (status) {
                    case 200:
                        if (responseXML) {
                            self.onDataReady(parseData(responseXML));
                        }
                        break;

                    case 404:
                    default:
                        break;
                }

                onreadystatechange = null;
                self.request = undefined;
            }
        }
    }

    function parseData(data) {
        try {
            var result = new Object();
            var root = data.documentElement;
            var version = root.attributes.getNamedItem("version");

            if (!version || version.value != gForecastVersion) {
                return;
            }

            result.lastUpdated = new Date(root.attributes.getNamedItem("last_updated").value);

            with (root.selectSingleNode("city")) {
                var regionNode = selectSingleNode("region/name");

                result.city = {
                    id: attributes.getNamedItem("id").text,
                    name: selectSingleNode("name").text,
                    region: regionNode ? regionNode.text : "",
                    country: selectSingleNode("country/name").text
                };
            }

            with (root.selectSingleNode("current")) {
                if (attributes.length > 0 && childNodes.length > 0) {
                    result.locator = {
                        lastUpdated: new Date(attributes.getNamedItem("last_updated").value),
                        expires: new Date(attributes.getNamedItem("expires").value),
                        time: new Date(selectSingleNode("time").text),
                        cloudiness: parseInt(selectSingleNode("cloud").text),
                        pict: selectSingleNode("pict").text,
                        temperature: {
                            value: parseInt(selectSingleNode("t").text),
                            feel: parseInt(selectSingleNode("t_flik").text)
                        },
                        pressure: parseInt(selectSingleNode("p").text),
                        wind: {
                            speed: parseInt(selectSingleNode("w").text),
                            course: parseInt(selectSingleNode("w_rumb").text)
                        },
                        humidity: parseInt(selectSingleNode("h").text)
                    };
                }
            }
            //}

            result.forecast = new Array();

            var forecast = root.selectNodes("forecast/day");

            for (var index = 0; index < forecast.length; index++) {
                var item = parseForecast(forecast.item(index));

                result.forecast.push(item);
            }

            return result;
        }
        finally {
            with (waiter.style) {
                display = "none";
                visibility = "hidden";
            }
        }
    }

    function parseForecast(data) {
        with (data) {
            return {
                date: parseIsoDate(attributes.getNamedItem("date").value),
                hour: parseInt(attributes.getNamedItem("hour").value),
                cloudiness: parseInt(selectSingleNode("cloud").text),
                pict: selectSingleNode("pict").text,
                precipitation: parseInt(selectSingleNode("ppcp").text),
                temperature: parseMinMaxValues(selectSingleNode("t")),
                pressure: parseMinMaxValues(selectSingleNode("p")),
                wind: {
                    min: parseInt(selectSingleNode("wind/min").text),
                    max: parseInt(selectSingleNode("wind/max").text),
                    course: parseInt(selectSingleNode("wind/rumb").text)
                },
                humidity: parseMinMaxValues(selectSingleNode("hmid")),
                probability: parseInt(selectSingleNode("wpi").text)
            };
        }
    }

    function parseMinMaxValues(node) {
        with (node) {
            return {
                min: parseInt(selectSingleNode("min").text),
                max: parseInt(selectSingleNode("max").text)
            };
        }
    }

    function parseIsoDate(datestring) {
        var data = new String(datestring).split('-');
        return new Date(parseInt(data[0]), parseInt(data[1]) - 1, parseInt(data[2]));
    }

    function onRequestTimeout() {
        if (self.request) {
            with (self.request) {

                onreadystatechange = null;

                if (readyState == 4) {
                    return;
                }

                abort();
            }
            self.request = undefined;
        }
    }

    this.performRequest = function() {
        try {
            self.request = new XMLHttpRequest();

            with (waiter.style) {
                display = "block";
                visibility = "visible";
            }

            requestTimeout = setTimeout(onRequestTimeout, 30000);

            with (self.request) {
                open("GET", gServiceUrl + options.city.id + "?dayf=" + 1 + "&lang=ru" + "&userid=code_google_com/p/weathergadget/");
                setRequestHeader("If-Modified-Since", Date().toString());
                onreadystatechange = parseResponse;
                send(null);
            }
        }
        catch (e) {
            alert(e);
        }
    }

    this.beginPoll = function() {
        self.performRequest();
        pollTimeout = setTimeout(self.beginPoll, gPollTimeout);
    }

    this.reset = function() {
        options.load();
        if (pollTimeout) {
            clearTimeout(pollTimeout);
        }
        self.beginPoll();
    }
}